package com.ruoyi.cs.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.Response;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.redis.RedisLock;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.cs.domain.*;
import com.ruoyi.cs.domain.dto.battle.*;
import com.ruoyi.cs.domain.vo.*;
import com.ruoyi.cs.mapper.*;
import com.ruoyi.cs.service.*;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.mapper.SysDictDataMapper;
import com.ruoyi.system.service.ISysDictDataService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * 盲盒对战信息Service业务层处理
 *
 * @author ruoyi
 * @date 2021-08-05
 */
@Service
@SuppressWarnings("all")
public class TBattleInfoServiceImpl implements ITBattleInfoService

{
    private static final Logger log = LoggerFactory.getLogger(TBattleInfoServiceImpl.class);
    @Autowired
    private TBattleInfoMapper tBattleInfoMapper;
    @Autowired
    private TBattleUserMapper tBattleUserMapper;
    @Autowired
    private TBattleBoxMapper tBattleBoxMapper;
    @Autowired
    private TBoxMapper tBoxMapper;
    @Autowired
    private TGoodsMapper tGoodsMapper;
    @Autowired
    private TUserMapper tUserMapper;
    @Autowired
    private SysDictDataMapper sysDictDataMapper;
    @Autowired
    private ISysDictDataService sysDictDataService;
    @Autowired
    private TBackpackMapper tBackpackMapper;
    @Autowired
    private ITBoxService tBoxService;
    @Autowired
    private TBalanceChangeMapper balanceChangeMapper;
    @Autowired
    private SysConfigMapper sysConfigMapper;
    @Autowired
    private ITWarService tWarService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private TRechargeMapper tRechargeMapper;
    @Autowired
    private TBattleCreateBoxMapper tBattleCreateBoxMapper;
    @Autowired
    private TBattleSpoilsMapper tBattleSpoilsMapper;
    @Autowired
    private RedisLock redisLock;
    @Autowired
    private CommonService commonService;
    @Autowired
    private ITVipUserService tVipUserService;

    @Value("${battle.starttime}")
    private String battleStartTime;

    /**
     * 查询盲盒对战信息
     *
     * @param battleId 盲盒对战信息ID
     * @return 盲盒对战信息
     */
    @Override
    public TBattleInfo selectTBattleInfoById(String battleId)
    {
        return tBattleInfoMapper.selectTBattleInfoById(battleId);
    }

    /**
     * 查询盲盒对战信息列表
     *
     * @param tBattleInfo 盲盒对战信息
     * @return 盲盒对战信息
     */
    @Override
    public List<TBattleInfo> selectTBattleInfoList(TBattleInfo tBattleInfo)
    {
        return tBattleInfoMapper.selectTBattleInfoList(tBattleInfo);
    }

    /**
     * 新增盲盒对战信息
     *
     * @param tBattleInfo 盲盒对战信息
     * @return 结果
     */
    @Override
    public int insertTBattleInfo(TBattleInfo tBattleInfo)
    {
        tBattleInfo.setCreateTime(DateUtils.getNowDate());
        return tBattleInfoMapper.insertTBattleInfo(tBattleInfo);
    }

    /**
     * 修改盲盒对战信息
     *
     * @param tBattleInfo 盲盒对战信息
     * @return 结果
     */
    @Override
    public int updateTBattleInfo(TBattleInfo tBattleInfo)
    {
        tBattleInfo.setUpdateTime(DateUtils.getNowDate());
        return tBattleInfoMapper.updateTBattleInfo(tBattleInfo);
    }

    /**
     * 批量删除盲盒对战信息
     *
     * @param battleIds 需要删除的盲盒对战信息ID
     * @return 结果
     */
    @Override
    public int deleteTBattleInfoByIds(String[] battleIds)
    {
        return tBattleInfoMapper.deleteTBattleInfoByIds(battleIds);
    }

    /**
     * 删除盲盒对战信息信息
     *
     * @param battleId 盲盒对战信息ID
     * @return 结果
     */
    @Override
    public int deleteTBattleInfoById(String battleId)
    {
        return tBattleInfoMapper.deleteTBattleInfoById(battleId);
    }

    /**
     * 获取所有对战的盲盒列表
     * @return
     */
    @Override
    public List<TBox> battleBoxList(PageInfoParamVo pageInfoParamVo) {
        List<TBox> list = tBoxMapper.battleBoxList(pageInfoParamVo);
        if (list != null && list.size()>0) {
            list.stream().forEach(bean -> {
                TGoods tGoods = tGoodsMapper.boxGoodsMaxPrice(Constants.GOOGSBLTYPE0,bean.getBoxId());
                if(tGoods != null){
                    bean.setGoodsPic(tGoods.getGoodsPic());
                }
            });
        }
        return list;
    }

    /**
     * 创建盲盒对战
     * @param tBattleInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response<Map> createBattle(String userId, TbattleCreateVo tbattleCreateVo){
        List<String> boxIds = tbattleCreateVo.getBoxs();

        /**判断当前用户是否有对战的资格*/
        TUser tUser = tUserMapper.selectTUserById(userId);
        if (tUser == null || !Constants.SUCCESS.equals(tUser.getDelFlag())) {
            return Response.fail(Constants.FAILCODE, "账户不存在或已停用！");
        }
        if (!Constants.ISBATTLE0.equals(tUser.getIsBattle())) {
            return Response.fail(Constants.FAILCODE, "无参与对战的资格！");
        }
        SysDictData sysDictData1 = sysDictDataMapper.selectDictDataById(190L);
        if (!Constants.SUCCESS.equals(sysDictData1.getDictValue())) {
            return Response.fail(Constants.FAILCODE, "暂未开放对战平台！");
        }
        SysDictData sysDictData2 = sysDictDataMapper.selectDictDataById(191L);
        if (Constants.SUCCESS.equals(sysDictData2.getDictValue()) && Constants.USERTYPE1.equals(tUser.getUserType())) {
            return Response.fail(Constants.FAILCODE, "无法参与平台对战！");
        }
        SysConfig sysConfig = sysConfigMapper.checkConfigKeyUnique("open_battle_recharge_threshold");
        BigDecimal thresholdMoney = new BigDecimal(sysConfig.getConfigValue());

        if (tUser.getUserType().equals("0") && tUser.getUserTotalRecharge().compareTo(thresholdMoney) < 0){
            return Response.fail(Constants.FAILCODE,"累计充值满"+thresholdMoney.intValue()+"金币方可参加！");
        }

        List<TBox> boxes = tBoxMapper.getTBoxListBatch(Constants.SUCCESS, boxIds);
        List<TBox> collect = boxes.stream().filter(b -> !(Constants.BOXTYPE1.equals(b.getBoxType()))).collect(Collectors.toList());
        if (collect.size() > 0) {
            return Response.fail(Constants.FAILCODE, "所选箱子有误，请刷新页面后重试！");
        }

        List<TBox> tBoxList = new ArrayList<>();
        for (String boxId : boxIds) {
            List<TBox> boxList = boxes.stream().filter(bean -> boxId.equals(bean.getBoxId())).collect(Collectors.toList());
            if (boxList.size() > 0) {
                tBoxList.add(boxList.get(0));
            } else {
                return Response.fail(Constants.FAILCODE, "请刷新页面重试！");
            }
        }
        /**对战费用*/
        BigDecimal battlefee = tBoxList.stream().map(TBox::getBoxPrice).reduce(BigDecimal.ZERO,BigDecimal::add);
        String battleType = tUser.getUserType().equals(Constants.USERTYPE0) ? Constants.BATTLETYPE0 : (tUser.getUserType().equals(Constants.USERTYPE1)? (tbattleCreateVo.getIsFansBattle() ? Constants.BATTLETYPE3 : Constants.BATTLETYPE1):Constants.BATTLETYPE2);

        /**主播创建粉丝对战增加条件判断*/
        if(battleType.equals(Constants.BATTLETYPE3)){
            //是否允许主播创建免费对战
            Boolean isFanBattleEnabled = tUser.getIsFanBattleEnabled();
            //单次对战额度
            BigDecimal singleBattleLimit = tUser.getSingleBattleLimit();
            //总对战额度
            BigDecimal totalBattleLimit = tUser.getTotalBattleLimit();
            //每日创建免费对战次数
            Integer dailyFreeBattleCount = tUser.getDailyFreeBattleCount();

            if(!isFanBattleEnabled){
                return Response.fail(Constants.FAILCODE, "不允许创建");
            }
            if(battlefee.compareTo(singleBattleLimit)>0){
                return Response.fail(Constants.FAILCODE, "不符合单次对战额度条件，无法创建");
            }
            /**统计主播创建的总粉丝对战的金额*/
            BigDecimal fansBattleTotalFee = tBattleInfoMapper.countFansBattleTotalFee(userId);
            fansBattleTotalFee = fansBattleTotalFee == null ? battlefee : fansBattleTotalFee.add(battlefee);
            if(fansBattleTotalFee.compareTo(totalBattleLimit) > 0){
                return Response.fail(Constants.FAILCODE, "不符合总对战额度条件，无法创建");
            }

            Long fansBattleNumber = tBattleInfoMapper.countFansBattleNumber(userId);
            fansBattleNumber = fansBattleNumber+1;
            if(fansBattleNumber>dailyFreeBattleCount){
                return Response.fail(Constants.FAILCODE, "已超出每日可创建粉丝对战次数");
            }
        }

        if (tbattleCreateVo.getChooseRobot()) {
            if(StringUtils.isEmpty(tbattleCreateVo.getPitlocation()) || Integer.parseInt(tbattleCreateVo.getPitlocation())<2 || Integer.parseInt(tbattleCreateVo.getPitlocation())>Integer.parseInt(tbattleCreateVo.getBattleNum())){
                return Response.fail(Constants.FAILCODE, "如需加入机器人，则选择对应的坑位");
            }
        }

        /**用户余额*/
        BigDecimal balance = tUser.getUserBalance();
        /**第二套货币*/
        BigDecimal secondCurrency = tUser.getSecondCurrency();
        /**用户可消费金额*/
        BigDecimal consumableFee = balance.add(secondCurrency);
        if (consumableFee.compareTo(battlefee) < 0) {
            return Response.fail(Constants.FAILCODE, "余额不足，请先充值！");
        }

        /**开始创建对战信息*/
        String battleId = IdUtil.fastSimpleUUID();
        TBattleInfo info = new TBattleInfo();
        info.setBattleId(battleId);
        info.setHomeownerUserid(tUser.getUserId());
        info.setHomeownerCost(battlefee);
        info.setBattleStatus(Constants.BATTLEINFOSTATUS0);
        info.setCreateTime(DateUtils.getNowDate());
        info.setBattleType(battleType);
        info.setCostRangeType(tbattleCreateVo.getCostRangeType());
        info.setFanPwd(tbattleCreateVo.getFanPwd());
        info.setBattleMode(Integer.parseInt(tbattleCreateVo.getBattleMode()));
        info.setDailyRechargeAmount(tUser.getDailyRechargeAmount());
        info.setTotalRechargeAmount(tUser.getTotalRechargeAmount());
        info.setBattleNum(Integer.parseInt(tbattleCreateVo.getBattleNum()));
        tBattleInfoMapper.insertTBattleInfo(info);

        String battlerUserId = IdUtils.fastSimpleUUID();
        TBattleUser tBattleUser = new TBattleUser();
        tBattleUser.setBattleId(battleId);
        tBattleUser.setBattleruserId(battlerUserId);
        tBattleUser.setUserId(tUser.getUserId());
        tBattleUser.setCost(battlefee);
        tBattleUser.setDzStatus(null);
        tBattleUser.setCreateTime(DateUtils.getNowDate());
        tBattleUser.setUserType(tUser.getUserType());
        tBattleUser.setCreatTimeStamp(System.currentTimeMillis());
        tBattleUser.setPitlocation("1");
        tBattleUserMapper.insertTBattleUser(tBattleUser);


        List<TBattleCreateBox> battleCreateBoxList = tBoxList.stream().map(box -> {
            return TBattleCreateBox.builder()
                    .battleId(battleId)
                    .boxId(box.getBoxId())
                    .boxName(box.getBoxName())
                    .boxPic(box.getBoxPic())
                    .boxPrice(box.getBoxPrice())
                    .createTime(DateUtils.getNowDate())
                    .build();
        }).collect(Collectors.toList());
        tBattleCreateBoxMapper.batchInsertBattleCreateBox(battleCreateBoxList);

        /**开启后余额*/
        BigDecimal openAfterBalance = tUser.getUserBalance();
        /**开启后货币余额*/
        BigDecimal openAfterSecondCurrency = tUser.getSecondCurrency();

        if(openAfterBalance.compareTo(battlefee) >=0){
            /**普通箱子开箱 扣除余额*/
            openAfterBalance = openAfterBalance.subtract(battlefee);
        }else if(openAfterBalance.compareTo(BigDecimal.ZERO) > 0 && openAfterBalance.compareTo(battlefee) < 0){
            openAfterSecondCurrency = openAfterSecondCurrency.subtract(battlefee.subtract(openAfterBalance));
            openAfterBalance = BigDecimal.ZERO;
        }else {
            openAfterSecondCurrency = openAfterSecondCurrency.subtract(battlefee);
        }

        /**插入余额变更表*/
        TBalanceChange balanceChange = new TBalanceChange();
        balanceChange.setUserId(tUser.getUserId());
        balanceChange.setBalanceBefore(balance);
        balanceChange.setBalanceAfter(openAfterBalance);
        balanceChange.setOperationType(Constants.OPERATIONTYPE6);
        balanceChange.setFrequency(1);
        balanceChange.setFee(battlefee);
        balanceChange.setCorrespondingid(battleId);
        balanceChange.setCreateTime(DateUtils.getNowDate());
        balanceChange.setStatus(0);
        balanceChange.setSecondCurrencyBefore(secondCurrency);
        balanceChange.setSecondCurrencyAfter(openAfterSecondCurrency);
        balanceChangeMapper.insertTBalanceChange(balanceChange);

        /**修改用户余额*/
        tUser.setUserBalance(openAfterBalance);
        tUser.setSecondCurrency(openAfterSecondCurrency);
        int row = tUserMapper.updateTUserBalance(tUser);
        if (row == 0) {
            throw new CustomException("请重新创建对战！");
        }

        /**获取多个箱子中的所有饰品，把当前饰品保存至redis中**/
        List<TGoods> boxGoodsList = tGoodsMapper.battleBoxGoods(boxIds);
        List<BattleGoodsRedisVo> redisGoods = BeanUtil.copyToList(boxGoodsList,BattleGoodsRedisVo.class);
        String key = Constants.BATTLE_GOODS_PRE_KEY+battleId;
        redisCache.setCacheObject(key,JSON.toJSONString(redisGoods),30, TimeUnit.DAYS);
        Map resmap = new LinkedHashMap();
        resmap.put("battleId",battleId);
        resmap.put("battleStatu",Constants.BATTLEINFOSTATUS0);

        /*勾选机器人*/
        if (tbattleCreateVo.getChooseRobot()) {
            /*判断是否指定机器人*/
            String robatId = tbattleCreateVo.getRobatId();
            if (StringUtils.isEmpty(tbattleCreateVo.getRobatId())) {
                /*查询出余额大于当前开箱价格的机器人*/
                List<TUser> battleRobot = tUserMapper.selectBattleRobot(battlefee.toString());
                if (!CollectionUtils.isEmpty(battleRobot)) {
                    Random r = new Random();
                    int i = r.nextInt(battleRobot.size());
                    robatId = battleRobot.get(i).getUserId();
                }
            }
            info.setChooseRobot(tbattleCreateVo.getChooseRobot());

            BattleStartReq req = new BattleStartReq();
            req.setBattleId(battleId);
            req.setChooseRobot(true);
            req.setRobatId(robatId);
            req.setPitlocation(tbattleCreateVo.getPitlocation());
            return startBattleV2(req,tUser.getUserId());

        }
        return Response.success(resmap);
    }

    @Override
    public List<TBattleBackVo> selectTBattleInfoList(List<TBattleInfo> list) {
        List<TBattleBackVo> result = new ArrayList<>();
        if (StringUtils.isNotNull(list) && list.size() > 0) {
            for (TBattleInfo bean : list) {
                TBattleBackVo vo = new TBattleBackVo();
                vo.setBattleId(bean.getBattleId());
                vo.setBattleTime(bean.getBattleTime());
                vo.setHomeownerId(bean.getHomeownerUserid());
                vo.setHomeownerName(bean.getHomeownerUserName());
                vo.setBattleType(bean.getBattleType());

                BigDecimal totalfee = new BigDecimal(0);
                if (bean.getBattleStatus().equals(Constants.BATTLEINFOSTATUS1) || bean.getBattleStatus().equals(Constants.BATTLEINFOSTATUS2)) {/*对战结束状态*/

                    List<Map> homeownerGoods = new ArrayList<>();
                    /**房主*/
                    BigDecimal homeownerGoodsPrice = new BigDecimal(0);
                    List<TBattleUser> tBattleUsers = bean.getTBattleUserList().stream().filter(ss -> bean.getHomeownerUserid().equals(ss.getUserId())).collect(Collectors.toList());
                    TBattleUser tBattleUser = tBattleUsers.get(0);
                    vo.setHomeownerPhone(tBattleUser.getUserPhone());
                    List<TBattleBox> tBattleBoxList = tBattleUser.getTBattleBoxList();
                    for (TBattleBox tBattleBox : tBattleBoxList) {
                        Map map = new HashMap();
                        map.put("goodsName", tBattleBox.getGoodsName());
                        map.put("goodsPic", tBattleBox.getGoodsPic());
                        homeownerGoods.add(map);

                        homeownerGoodsPrice = homeownerGoodsPrice.add(tBattleBox.getGoodsPrice());
                    }
                    vo.setHomeownerGoods(homeownerGoods);
                    vo.setHomeownerGoodsPrice(homeownerGoodsPrice);
                    if (Constants.USERTYPE0.equals(tBattleUser.getUserType())) {
                        totalfee = totalfee.add(homeownerGoodsPrice);
                    }

                    List<Map> boxList = new ArrayList<>();
                    for (TBattleBox tBattleBox : tBattleBoxList) {
                        Map map = new HashMap();
                        map.put("boxName", tBattleBox.getBoxName());
                        map.put("boxPic", tBattleBox.getBoxPic());
                        boxList.add(map);
                    }
                    vo.setBoxList(boxList);

                    /**对战者*/
                    List<Map> partakeGoods = new ArrayList<>();
                    BigDecimal partakeGoodsPrice = new BigDecimal(0);

                    List<TBattleUser> dzList = bean.getTBattleUserList().stream().filter(ss -> !bean.getHomeownerUserid().equals(ss.getUserId())).collect(Collectors.toList());

                    TBattleUser dz = dzList.get(0);
                    vo.setPartakeId(dz.getUserId());
                    vo.setPartakeName(dz.getUserName());
                    vo.setPartakePhone(dz.getUserPhone());
                    List<TBattleBox> dzBoxList = dz.getTBattleBoxList();
                    for (TBattleBox tBattleBox : dzBoxList) {
                        Map map = new HashMap();
                        map.put("goodsName", tBattleBox.getGoodsName());
                        map.put("goodsPic", tBattleBox.getGoodsPic());
                        partakeGoods.add(map);
                        partakeGoodsPrice = partakeGoodsPrice.add(tBattleBox.getGoodsPrice());
                    }
                    vo.setPartakeGoods(partakeGoods);
                    vo.setPartakeGoodsPrice(partakeGoodsPrice);

                    if (Constants.USERTYPE0.equals(dz.getUserType())) {
                        totalfee = totalfee.add(partakeGoodsPrice);
                    }
                    vo.setGoodsPriceTotal(totalfee);

                } else {
                    /*对战未结束状态*/
                    List<TBattleUser> tBattleUsers = bean.getTBattleUserList().stream().filter(ss -> bean.getHomeownerUserid().equals(ss.getUserId())).collect(Collectors.toList());
                    TBattleUser battleUser = tBattleUsers.get(0);
                    vo.setHomeownerPhone(battleUser.getUserPhone());
                    List<TBattleBox> tBattleBoxList = battleUser.getTBattleBoxList();
                    List<Map> boxList = new ArrayList<>();
                    for (TBattleBox tBattleBox : tBattleBoxList) {
                        Map map = new HashMap();
                        map.put("boxName", tBattleBox.getBoxName());
                        map.put("boxPic", tBattleBox.getBoxPic());
                        boxList.add(map);
                    }
                    vo.setBoxList(boxList);
                }
                /**开箱总金额*/
                BigDecimal costTotal = new BigDecimal(0);
                List<TBattleUser> tBattleUsers = bean.getTBattleUserList();
                for (TBattleUser tBattleUser : tBattleUsers) {
                    if (Constants.USERTYPE0.equals(tBattleUser.getUserType())) {
                        costTotal = costTotal.add(tBattleUser.getCost());
                    }
                }
                vo.setCostTotal(costTotal);
                if (bean.getBattleStatus().equals(Constants.BATTLEINFOSTATUS1) || bean.getBattleStatus().equals(Constants.BATTLEINFOSTATUS2)) {
                    List<TBackPackVo> backpackListBattle = tBackpackMapper.selectBackpackListBattle(bean.getBattleId());
                    List<TBackPackVo> acquiredGoodsList = new ArrayList<>();
                    for (TBattleUser battleUser : tBattleUsers) {
                        acquiredGoodsList = backpackListBattle.stream().filter(backpack -> backpack.getUserId().equals(battleUser.getUserId())).collect(Collectors.toList());

                        BigDecimal acquiredGoodsExprice = acquiredGoodsList.stream().map(TBackPackVo::getGoodsExprice).reduce(BigDecimal.ZERO, BigDecimal::add);
                        if (bean.getHomeownerUserid().equals(battleUser.getUserId())) {
                            List<Map> winnerGoods = new ArrayList<>();
                            for (TBackPackVo tBackpack : acquiredGoodsList) {
                                Map map = new HashMap();
                                map.put("goodsName", tBackpack.getGoodsName());
                                map.put("goodsPic", tBackpack.getGoodsPic());
                                winnerGoods.add(map);
                            }
                            vo.setWinnerGoods(winnerGoods);
                        } else {
                            List<Map> failnerGoods = new ArrayList<>();
                            for (TBackPackVo tBackpack : acquiredGoodsList) {
                                Map map = new HashMap();
                                map.put("goodsName", tBackpack.getGoodsName());
                                map.put("goodsPic", tBackpack.getGoodsPic());
                                failnerGoods.add(map);
                            }
                            vo.setFailnerGoods(failnerGoods);
                        }
                    }

                    vo.setProfit(costTotal.subtract(totalfee));
                }
                result.add(vo);
            }
        }
        return result;
    }

    @Override
    public List<TBattleInfo> battleBackList(TBattleBackVo tBattleBackVo) {
        List<TBattleInfo> list = tBattleInfoMapper.battleBackList(tBattleBackVo);
        if (list != null && list.size()>0){
            List<String> battleIds = list.stream().map(TBattleInfo::getBattleId).collect(Collectors.toList());
            /**对战用户*/
            List<TBattleUser> tBattleUsers = tBattleUserMapper.selectBattleUserByBattleId(battleIds);
            Map<String, List<TBattleUser>> userMap = tBattleUsers.stream().collect(Collectors.groupingBy(TBattleUser::getBattleId));
            /**对战箱子*/
            List<TBattleBox> tBattleBoxList = tBattleBoxMapper.getBattleBoxByBattleIds(battleIds);
            Map<String, List<TBattleBox>> boxMap = tBattleBoxList.stream().collect(Collectors.groupingBy(TBattleBox::getBattleId));

            for (TBattleInfo battleInfo : list) {
                battleInfo.setTBattleUserList(userMap.get(battleInfo.getBattleId()));
                List<TBattleBox> tBattleBoxes = boxMap.get(battleInfo.getBattleId());
                Map<String, List<TBattleBox>> userBoxMap = tBattleBoxes.stream().collect(Collectors.groupingBy(TBattleBox::getUserId));

                for (TBattleUser tBattleUser : battleInfo.getTBattleUserList()) {
                    tBattleUser.setTBattleBoxList(userBoxMap.get(tBattleUser.getUserId()));
                }
            }
        }
        return list;
    }

    @Override
    public Response<Map> count(String startTime, String endTime) {
        Map total = tBattleInfoMapper.countTotal(startTime, endTime);
        Map today = tBattleInfoMapper.countToday();
        total.putAll(today);
        return Response.success(total);
    }

    @Override
    public List<Map> boxCountList(TBattleBoxCountVo tBattleBoxCountVo) {
        return tBattleInfoMapper.boxCountList(tBattleBoxCountVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void obsoleteBattle(TBattleInfo tBattleInfo) throws Exception{
        String battleId = tBattleInfo.getBattleId();
        List<TBattleUser> userList = tBattleUserMapper.getBattleUserListByBattleId(battleId);
        int count = tBattleInfoMapper.updateStatusById(battleId);
        if (count > 0 && CollectionUtil.isNotEmpty(userList)){
            userList.forEach(bean -> {
                TUser user = tUserMapper.selectTUserById(bean.getUserId());
                if(user.getUserType().equals(Constants.USERTYPE0) || user.getUserType().equals(Constants.USERTYPE1)){
                    BigDecimal balanceBefore = user.getUserBalance();

                    user.setUserBalance(user.getUserBalance().add(bean.getCost()));
                    int row = tUserMapper.updateTUserBalance(user);
                    if (row == 0){
                        throw new CustomException("用户余额没修改成功");
                    }

                    TBalanceChange balanceChange= new TBalanceChange();
                    balanceChange.setUserId(bean.getUserId());
                    balanceChange.setBalanceBefore(balanceBefore);
                    balanceChange.setBalanceAfter(user.getUserBalance());
                    balanceChange.setOperationType(Constants.OPERATIONTYPE61);
                    balanceChange.setFrequency(1);
                    balanceChange.setFee(bean.getCost());
                    balanceChange.setCorrespondingid(battleId);
                    balanceChange.setCreateTime(DateUtils.getNowDate());
                    balanceChange.setProfitPrice(BigDecimal.ZERO);
                    balanceChange.setSecondCurrencyAfter(user.getSecondCurrency());
                    balanceChange.setSecondCurrencyBefore(user.getSecondCurrency());
                    balanceChangeMapper.insertTBalanceChange(balanceChange);
                }
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void battleOver() {
        List<TBattleInfo> battleList = tBattleInfoMapper.selectAminuteAgo();
        if (battleList.size() > 0) {
            List<String> battleIdList = battleList.stream().map(TBattleInfo::getBattleId).collect(Collectors.toList());
            int i = tBattleInfoMapper.updateBattleInfoStatus(battleIdList);
            if(i > 0){
                log.info("定时修改对战间状态成功：{}条",battleIdList.size());
            }
            List<TBattleInfo> filterList = battleList.stream().filter(bean -> bean.getBattleType().equals(Constants.BATTLETYPE3)).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(filterList)){
                List<String> filterIds = filterList.stream().map(TBattleInfo::getBattleId).collect(Collectors.toList());
                List<TBattleUser>  tBattleUsers = tBattleUserMapper.battleUserListGroupType(filterIds,Constants.USERTYPE0);
                Map<String, BigDecimal> map = tBattleUsers.stream().collect(Collectors.toMap(TBattleUser::getUserId,user -> {
                    BigDecimal cost = user.getCost();
                    BigDecimal battleFee = user.getBattleFee();
                    String dzStatus = user.getDzStatus();

                    if(dzStatus.equals("0")){
                        return cost;
                    }else {
                        return  cost.compareTo(battleFee) > 0 ? cost.subtract(battleFee) : BigDecimal.ZERO;
                    }
                })).entrySet().stream().filter(entry -> entry.getValue().compareTo(BigDecimal.ZERO) > 0)
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
                /**补偿用户金额*/
                if(!map.isEmpty()){
                    int row = tBattleUserMapper.increaseUserCompensation(map);
                    log.info("粉丝对战补偿，补偿用户个数:{},补偿具体的金额:{}",row, JSON.toJSONString(map));
                }
            }
        }else {
            log.info("指定时间内无对战中的对战间！");
        }
    }

    @Override
    public List<BattleBaseResp> battleListV2(String battleListType, String userId) {
        List<BattleBaseResp> list = tBattleInfoMapper.battleList1("0".equals(battleListType) ? userId : null,battleStartTime);
        if(CollectionUtil.isEmpty(list)){
            return new ArrayList<>();
        }

        List<String> battleIds = list.stream().map(BattleBaseResp::getBattleId).collect(Collectors.toList());
        /**用戶集合*/
        List<TBattleUser> tBattleUsers = tBattleUserMapper.selectBattleUserByBattleId(battleIds);
        Map<String, List<TBattleUser>> tBattleUserMap = tBattleUsers.stream()
                .collect(Collectors.groupingBy(TBattleUser::getBattleId));

        /**对战箱子集合*/
        List<TBattleCreateBox> battleCreateBoxs = tBattleCreateBoxMapper.batchBattleBoxListByBattleId(battleIds);
        Map<String, List<TBattleCreateBox>> battleCreateBoxMap = battleCreateBoxs.stream()
                .collect(Collectors.groupingBy(TBattleCreateBox::getBattleId));

        /**获取所有箱子ID*/
        List<String> boxIds = battleCreateBoxs.stream().map(TBattleCreateBox::getBoxId).distinct().collect(Collectors.toList());
        List<TGoods> tGoodsList = tGoodsMapper.battleBoxGoods(boxIds);
        Map<String, List<TGoods>> tGoodsMap = tGoodsList.stream()
                .collect(Collectors.groupingBy(TGoods::getGoodsBelongingId));


        for (BattleBaseResp res : list) {
            if(res.getHomeownerUserid().equals(userId)){
                res.setIsHomeUser(true);
            }else {
                res.setIsHomeUser(false);
            }
            /**设置用户*/
            List<TBattleUser> users = tBattleUserMap.get(res.getBattleId());
            List<BattleBaseResp.BattleUserVo> battleUserVos = users.stream().map(user -> {
                    return BattleBaseResp.BattleUserVo.builder()
                            .userPic(user.getUserPic())
                            .userName(user.getUserName())
                            .pitlocation(user.getPitlocation())
                            .build();
                }).collect(Collectors.toList());
            res.setUserVoList(battleUserVos);
            /**设置箱子*/
            List<TBattleCreateBox> boxs = battleCreateBoxMap.get(res.getBattleId());
            List<BattleBoxVo> battleBoxVoList = boxs.stream().map(t -> toBattleBoxVo(t,tGoodsMap.get(t.getBoxId()))).collect(Collectors.toList());
            res.setBoxVoList(battleBoxVoList);
        }
        return list;
    }

    public BattleBoxVo toBattleBoxVo(TBattleCreateBox box,  List<TGoods> tGoods){
        Optional<TGoods> maxPriceGoods = tGoods.stream()
                .max((g1, g2) -> g1.getGoodsPrice().compareTo(g2.getGoodsPrice()));

        return BattleBoxVo.builder()
                .boxId(box.getBoxId())
                .boxName(box.getBoxName())
                .boxPic(box.getBoxPic())
                .boxPrice(box.getBoxPrice())
                .goodsPic(maxPriceGoods.isPresent() ? maxPriceGoods.get().getGoodsPic() : null)
                .build();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response<Map> startBattleV2(BattleStartReq req, String currentUserId) {
        String battleId = req.getBattleId();
        /**查询出对战用户*/
        TUser battleUser = null;
        TBattleInfo battleInfo = tBattleInfoMapper.selectTBattleInfoById(battleId);
        /**判断是否勾选机器人*/
        if (req.getChooseRobot()) {
            if (!battleInfo.getHomeownerUserid().equals(currentUserId)) {
                return Response.fail(Constants.FAILCODE, "您不是该房间创建者，不能选择机器人对战！");
            }
            if(StringUtils.isEmpty(req.getPitlocation()) || Integer.parseInt(req.getPitlocation())<2 || Integer.parseInt(req.getPitlocation())>battleInfo.getBattleNum()){
                return Response.fail(Constants.FAILCODE, "如需加入机器人，则选择对应的坑位");
            }
            /**判断是否指定机器人*/
            if (StringUtils.isNotEmpty(req.getRobatId())) {
                battleUser = tUserMapper.selectTUserById(req.getRobatId());
            } else {
                /**查询出余额大于当前开箱价格的机器人*/
                List<TUser> battleRobot = tUserMapper.selectBattleRobot(battleInfo.getHomeownerCost().toString());
                if (!CollectionUtils.isEmpty(battleRobot)) {
                    Random r = new Random();
                    int i = r.nextInt(battleRobot.size());
                    battleUser = battleRobot.get(i);
                }
            }
            if (battleUser == null) {
                return Response.fail("未匹配到合适机器人");
            }
            if(battleInfo.getBattleType().equals(Constants.BATTLETYPE3)){
                return Response.fail("机器人不能参与粉丝对战！");
            }
        } else {
            battleUser = tUserMapper.selectTUserById(currentUserId);
            /**判断当前用户是否有对战的资格*/
            if (battleUser == null || !Constants.SUCCESS.equals(battleUser.getDelFlag())) {
                return Response.fail(Constants.FAILCODE, "账户不存在或已停用，请联系管理员处理！");
            }
        }
        if (!Constants.ISBATTLE0.equals(battleUser.getIsBattle())) {
            return Response.fail(Constants.FAILCODE, "您没有获取参与对战的资格！");
        }
        SysDictData sysDictData1 = sysDictDataMapper.selectDictDataById(190L);
        if (!Constants.SUCCESS.equals(sysDictData1.getDictValue())) {
            return Response.fail(Constants.FAILCODE, "前端暂未开放对战平台！");
        }
        SysDictData sysDictData2 = sysDictDataMapper.selectDictDataById(191L);
        if (Constants.SUCCESS.equals(sysDictData2.getDictValue()) && Constants.USERTYPE1.equals(battleUser.getUserType())) {
            return Response.fail(Constants.FAILCODE, "禁止主播参与平台对战！");
        }
        SysConfig sysConfig = sysConfigMapper.checkConfigKeyUnique("open_battle_recharge_threshold");
        BigDecimal thresholdMoney = new BigDecimal(sysConfig.getConfigValue());
        if (battleUser.getUserType().equals("0") && battleUser.getUserTotalRecharge().compareTo(thresholdMoney) < 0){
            return Response.fail(Constants.FAILCODE,"累计充值满"+thresholdMoney.intValue()+"金币方可参加！");
        }
        if (battleInfo == null) {
            return Response.fail(Constants.FAILCODE, "对战房间不存在，请刷新页面重试");
        }
        if (!Constants.BATTLEINFOSTATUS0.equals(battleInfo.getBattleStatus()) || !Constants.SUCCESS.equals(battleInfo.getDelFlag())) {
            return Response.fail(Constants.FAILCODE, "此房间已结束，请重新选择其他房间对战！");
        }
        if (battleUser.getUserId().equals(battleInfo.getHomeownerUserid())) {
            return Response.fail(Constants.FAILCODE, "房主本人不能加入！");
        }
        if (battleInfo.getBattleType().equals(Constants.BATTLETYPE0) || battleInfo.getBattleType().equals(Constants.BATTLETYPE1)) {
            /**判断用户类型*/
            SysConfig battleLimitConfig = sysConfigMapper.checkConfigKeyUnique("members_participate_in_official_battle");
            String battleLimit = battleLimitConfig == null || StringUtils.isEmpty(battleLimitConfig.getConfigValue()) ? "0" : battleLimitConfig.getConfigValue();

            if (battleLimit.equals("1")) {
                /**判仅允许普通用户参与普通对战、官方参与官方对战*/
                if (!battleInfo.getBattleType().equals(battleUser.getUserType())) {
                    /**此为官方对战，您无法参加，请选择会员对战！*/
                    String current = "";
                    String choose = "";
                    switch (battleInfo.getBattleType()) {
                        case "1":
                            current = "官方";
                            choose = "会员";
                            break;
                        case "0":
                            current = "会员";
                            choose = "官方";
                            break;
                    }
                    return Response.fail(Constants.FAILCODE, "此为" + current + "对战，您无法参加，请选择" + choose + "对战！");
                }
            } else if (battleLimit.equals("0")) {
                /**允许会员参与官方对战、但是不允许官方参与会员对战*/
                if (battleUser.getUserType().equals(Constants.USERTYPE1) && battleInfo.getBattleType().equals(Constants.BATTLETYPE0)) {
                    return Response.fail(Constants.FAILCODE, "此为会员对战，您无法参加，请选择官方对战！");
                }
            }
        }else if(battleInfo.getBattleType().equals(Constants.BATTLETYPE3)){
            /**粉丝对战，普通用户参与资格*/
            if(!battleUser.getUserType().equals(Constants.USERTYPE0)){
                return Response.fail(Constants.FAILCODE, "无资格参与粉丝对战！");
            }

            TUser homeUser = tUserMapper.selectTUserById(battleInfo.getHomeownerUserid());
            if(!homeUser.getIsFollowBattleEnabled()){
                if(!battleInfo.getHomeownerUserid().equals(battleUser.getUserPromotersId())){
                    return Response.fail(Constants.FAILCODE, "非主播粉丝不能参与粉丝对战！");
                }
            }
            if(!Objects.equals(battleInfo.getFanPwd(),req.getFanPwd())){
                return Response.fail(Constants.FAILCODE, "粉丝对战房间密码错误，加入对战失败！");
            }
            /**判断用户的日充值和总充值*/
            BigDecimal dailyRecharge = tRechargeMapper.selectTheDayCzCountByUserId(battleUser.getUserId());
            if(dailyRecharge.compareTo(battleInfo.getDailyRechargeAmount()) < 0){
                return Response.fail(Constants.FAILCODE, "不满足日充值条件，无法参与！");
            }
            if(battleUser.getUserTotalRecharge().compareTo(battleInfo.getTotalRechargeAmount()) < 0){
                return Response.fail(Constants.FAILCODE, "不满足总充值条件，无法参与！");
            }
        }
        String lockKey = Constants.START_BATTLE_LOCK + battleId;
        String lockTime = DateUtils.getTimeAfter(DateUtils.getNowDate(), 1);
        lockTime = Long.toString(DateUtils.parseDate(lockTime).getTime());

        try {
            boolean lockflag = redisLock.lock(lockKey, lockTime);
            if (lockflag) {
                /**判断当前对战坑位是否已被占*/
                long pitnum = tBattleUserMapper.getBattlePitLocation(battleId,req.getPitlocation());
                if(pitnum>0){
                    return Response.fail(Constants.FAILCODE, "当前对战所选坑位已被占,请刷新对战");
                }
                List<TBattleUser> battleUserList = tBattleUserMapper.getBattleUserListByBattleId(battleId);
                String userId = battleUser.getUserId();
                /**判断是否重复参与对战*/
                Long cynum = battleUserList.stream().filter(bean -> bean.getUserId().equals(userId)).count();
                if(cynum>0){
                    return Response.fail(Constants.FAILCODE, "在同一个对战房间，只允许参与一次");
                }

                return battleStart(battleId,battleUser,battleInfo,req.getPitlocation());
            }else {
                return Response.fail(Constants.FAILCODE, "对战同时间只能加入一人！");
            }
        } finally {
            redisLock.release(lockKey, lockTime);
        }
    }

    public Response<Map> battleStart(String battleId,TUser battleUser,TBattleInfo battleInfo,String pitlocation){

        /**获取房间的对战箱子*/
        List<TBattleCreateBox> tBattleCreateBoxList = tBattleCreateBoxMapper.battleBoxListByBattleId(battleId);
        /**对战费用*/
        BigDecimal battlefee = tBattleCreateBoxList.stream().map(TBattleCreateBox::getBoxPrice).reduce(BigDecimal.ZERO, BigDecimal::add);

        /**开启后余额*/
        BigDecimal openAfterBalance = battleUser.getUserBalance();
        /**开启后货币余额*/
        BigDecimal openAfterSecondCurrency = battleUser.getSecondCurrency();
        /**用户可消费金额*/
        BigDecimal consumableFee = openAfterBalance.add(openAfterSecondCurrency);
        if (!battleUser.getUserType().equals(Constants.USERTYPE4)) {/**非AI对战机器人*/
            if (battleUser.getUserType().contains(Constants.USERTYPE3)) {
                if (battleUser.getUserBalance().compareTo(battlefee) < 0) {
                    return Response.fail("机器人余额不足，请换选");
                }
            } else {
                if (consumableFee.compareTo(battlefee) < 0) {
                    return Response.fail(Constants.FAILCODE, "余额不足，请先充值！");
                }
            }
        }
        /**获取默认保底饰品*/
        SysDictData ss = sysDictDataService.selectDictDataById(200L);
        String floorsGoodsId = ss.getListClass();
        List<TGoods> floorList = tGoodsMapper.battleFloorsGoodsList(battlefee.toString());
        if (floorList != null && floorList.size() > 0) {
            floorsGoodsId = floorList.get(0).getGoodsId();
        }
        if (StringUtils.isEmpty(floorsGoodsId)) {
            return Response.fail(Constants.FAILCODE, "暂时补偿饰品缺货，请联系管理员！");
        }
        TGoods bcGoods = tGoodsMapper.selectTGoodsById(floorsGoodsId);
        if (bcGoods == null) {
            return Response.fail(Constants.FAILCODE, "请联系管理员,重新设置保底饰品！");
        }


        /**插入对战者对象*/
        TBattleUser tBattleUser = new TBattleUser();
        String battlerUserId = IdUtil.fastSimpleUUID();
        tBattleUser.setBattleruserId(battlerUserId);
        tBattleUser.setBattleId(battleId);
        tBattleUser.setUserId(battleUser.getUserId());
        tBattleUser.setCost(battlefee);
        tBattleUser.setDzStatus(null);
        tBattleUser.setCreateTime(DateUtils.getNowDate());
        tBattleUser.setUserType(battleUser.getUserType());
        tBattleUser.setCreatTimeStamp(System.currentTimeMillis());
        tBattleUser.setPitlocation(pitlocation);
        tBattleUserMapper.insertTBattleUser(tBattleUser);

        /**余额和第二套货币计算*/
        if(openAfterBalance.compareTo(battlefee) >=0){
            openAfterBalance = openAfterBalance.subtract(battlefee);
        }else if(openAfterBalance.compareTo(BigDecimal.ZERO) > 0 && openAfterBalance.compareTo(battlefee) < 0){
            openAfterSecondCurrency = openAfterSecondCurrency.subtract(battlefee.subtract(openAfterBalance));
            openAfterBalance = BigDecimal.ZERO;
        }else {
            openAfterSecondCurrency = openAfterSecondCurrency.subtract(battlefee);
        }
        /**插入用户流水*/
        TBalanceChange balanceChange = new TBalanceChange();
        balanceChange.setUserId(battleUser.getUserId());
        balanceChange.setBalanceBefore(battleUser.getUserBalance());
        balanceChange.setBalanceAfter(openAfterBalance);
        balanceChange.setOperationType(Constants.OPERATIONTYPE6);
        balanceChange.setFrequency(1);
        balanceChange.setFee(battlefee);
        balanceChange.setCorrespondingid(battleId);
        balanceChange.setCreateTime(DateUtils.getNowDate());
        balanceChange.setSecondCurrencyBefore(battleUser.getSecondCurrency());
        balanceChange.setSecondCurrencyAfter(openAfterSecondCurrency);
        balanceChange.setStatus(0);
        balanceChangeMapper.insertTBalanceChange(balanceChange);

        /**更新用户余额*/
        battleUser.setUserBalance(openAfterBalance);
        battleUser.setSecondCurrency(openAfterSecondCurrency);
        battleUser.setUpdateTime(DateUtils.getNowDate());
        int row = tUserMapper.updateTUserBalance(battleUser);
        if(row == 0){
            throw new CustomException("余额变更异常");
        }

        /**判断是否达到开启对战的人数*/
        List<TBattleUser> battleUserList = tBattleUserMapper.getBattleUserListByBattleId(battleId);


        if(battleInfo.getBattleNum() > battleUserList.size()){
            Map resmap = new LinkedHashMap();
            resmap.put("battleId",battleId);
            resmap.put("battleStatu",Constants.BATTLEINFOSTATUS0);
            return Response.success(resmap);
        }
        /**-----------开启对战----------**/
        /**批量查询出箱子下的所有饰品*/
        List<TGoods> battleBoxAlls = null;
        String key = Constants.BATTLE_GOODS_PRE_KEY+battleId;
        String result =  redisCache.getCacheObject(key);
        if(result != null){
            List<BattleGoodsRedisVo> goodsRedis =  JSON.parseArray(result,BattleGoodsRedisVo.class);
            List<String> goodsIds = goodsRedis.stream().map(BattleGoodsRedisVo::getGoodsId).collect(Collectors.toList());
            List<TGoods> resgoods = tGoodsMapper.bacthTGoodsList("0",goodsIds.toArray(new String[goodsIds.size()]));
            resgoods.forEach(bean -> {
                BattleGoodsRedisVo redisVo = goodsRedis.stream().filter(re -> re.getGoodsId().equals(bean.getGoodsId())).findFirst().get();
                bean.setGoodsChance(redisVo.getGoodsChance());
                bean.setGoodsPrice(redisVo.getGoodsPrice());
                bean.setGoodsExprice(redisVo.getGoodsPrice());
            });
            battleBoxAlls = resgoods;
        }else {
            log.info("对战详情页中对战ID：{},在redis中未找到相关饰品");
            List<String> boxIds = tBattleCreateBoxList.stream().map(TBattleCreateBox::getBoxId).distinct().collect(Collectors.toList());
            battleBoxAlls = tGoodsMapper.battleBoxGoods(boxIds);
        }
        Map<String, List<TGoods>> goodsBattleMap = battleBoxAlls.stream().collect(Collectors.groupingBy(TGoods::getGoodsBelongingId));
        /**对战用户开箱*/
        for (TBattleUser user : battleUserList) {
            List<TBattleBox> tBattleBoxes = new ArrayList<>();
            tBattleCreateBoxList.forEach(box -> {
                /**获取该箱子下面的饰品*/
                List<TGoods> tGoodsList = goodsBattleMap.get(box.getBoxId());
                /**服务端种子*/
                String serverSeed = HashUtil.generateServerSeed();
                /**随机整数*/
                int nonce = HashUtil.generateNonce();
                /**公共hash*/
                String commonHash = HashUtil.commonHashCode(user.getCurrentUserSeed(),serverSeed,nonce);
                /**roll值*/
                Long rollValue = HashUtil.rollValue(commonHash);
                /**hash算法开箱*/
                Map<String, String> goodsIdMap = tGoodsList.stream().collect(Collectors.toMap(TGoods::getGoodsId,TGoods::getRollValueRange));
                Map<String, TGoods> goodsMap = tGoodsList.stream().collect(Collectors.toMap(TGoods::getGoodsId,t -> t));
                String goodsId = RollValueUtil.rollItem(rollValue.intValue(),goodsIdMap);
                TGoods tGoods = goodsMap.get(goodsId);

                /**设置开箱roll参数值*/
                TBattleBox tBattleBox = BeanUtil.copyProperties(box,TBattleBox.class);
                tBattleBox.setBattleId(box.getBattleId());
                tBattleBox.setUserId(user.getUserId());
                tBattleBox.setGoodsId(tGoods.getGoodsId());
                tBattleBox.setGoodsPrice(tGoods.getGoodsPrice());
                tBattleBox.setGoodsExprice(tGoods.getGoodsExprice());
                tBattleBox.setGoodsType(tGoods.getGoodsType());
                tBattleBox.setUserType(user.getUserType());
                tBattleBox.setCreateTime(DateUtils.getNowDate());
                tBattleBox.setUserSeed(user.getCurrentUserSeed());
                tBattleBox.setServerSeed(serverSeed);
                tBattleBox.setCommonHash(commonHash);
                tBattleBox.setNonce(nonce);
                tBattleBox.setRollValue(rollValue);
                tBattleBox.setRollValueRange(tGoods.getRollValueRange());
                tBattleBox.setTGoods(tGoods);
                tBattleBoxes.add(tBattleBox);
            });
            user.setTBattleBoxList(tBattleBoxes);
            /**对战所得金额*/
            BigDecimal battleGoodsPrice = tBattleBoxes.stream().map(battleBox -> battleBox.getTGoods().getGoodsPrice()) .reduce(BigDecimal.ZERO, BigDecimal::add);
            user.setBattleFee(battleGoodsPrice);
            /**计算hash值，平局情况下使用hash得到的roll值判断*/
            String serverSeed = HashUtil.generateServerSeed();
            int nonce = HashUtil.generateNonce();
            String commonHash = HashUtil.commonHashCode(user.getCurrentUserSeed(),serverSeed,nonce);
            Long rollValue = HashUtil.rollValue(commonHash);
            user.setUserSeed(user.getCurrentUserSeed());
            user.setServerSeed(serverSeed);
            user.setNonce(nonce);
            user.setCommonHash(commonHash);
            user.setRollValue(rollValue);
        }

        /**计算对战输赢*/
        Optional<TBattleUser> winner = battleUserList.stream()
                .max(Comparator.comparing((TBattleUser user) -> {
                    /**普通对战模式*/
                    if(Constants.BATTLEMODE0.equals(battleInfo.getBattleMode())){
                        return user.getBattleFee();
                    } else {
                        /**非酋模式*/
                        return BigDecimal.valueOf(-1).multiply(user.getBattleFee());
                    }
                }).thenComparing((TBattleUser user) -> {
                    if(Constants.BATTLEMODE0.equals(battleInfo.getBattleMode())){
                        return user.getRollValue().intValue();
                    } else {
                        return -user.getRollValue().intValue();
                    }
                }));




        List<TBackpack> tBackpackList = new ArrayList<>();
        List<TBattleSpoils> tBattleSpoilsList = new ArrayList<>();
        battleUserList.stream().forEach(user -> {
            TBattleUser tBattleUser1 = winner.get();
            if(user.getUserId().equals(tBattleUser1.getUserId())){
                user.setDzStatus(Constants.BATTLEUSERSTATUS1);
            }else {
                user.setDzStatus(Constants.BATTLEUSERSTATUS0);
            }
            /**胜利者*/
            user.getTBattleBoxList().stream().forEach(battleBox -> {
                String bbId = IdUtil.fastSimpleUUID();
                TBackpack tBackpack = toTBackpack(battleBox,tBattleUser1,bbId);
                tBackpackList.add(tBackpack);

                TBattleSpoils tBattleSpoils = BeanUtil.copyProperties(battleBox.getTGoods(),TBattleSpoils.class);
                tBattleSpoils.setBattleId(tBattleUser1.getBattleId());
                tBattleSpoils.setUserId(tBattleUser1.getUserId());
                tBattleSpoils.setBbId(bbId);
                tBattleSpoilsList.add(tBattleSpoils);
            });
            /**失败方*/
            if(user.getDzStatus().equals(Constants.BATTLEUSERSTATUS0)){
                String bbId = IdUtil.fastSimpleUUID();
                TBackpack tBackpack = toBcTBackpack(bcGoods,user,bbId);
                tBackpackList.add(tBackpack);

                TBattleSpoils tBattleSpoils = BeanUtil.copyProperties(bcGoods,TBattleSpoils.class);
                tBattleSpoils.setBbId(bbId);
                tBattleSpoils.setBattleId(user.getBattleId());
                tBattleSpoils.setUserId(user.getUserId());
                tBattleSpoilsList.add(tBattleSpoils);
            }
        });

        Map<String, List<TBattleSpoils>> tBattleSpoilsMap =  tBattleSpoilsList.stream().collect(Collectors.groupingBy(TBattleSpoils::getUserId));
        battleUserList.stream().forEach(user -> {
            /**计算最终所得饰品价值*/
            BigDecimal finalGoodsPrice = tBattleSpoilsMap.get(user.getUserId()).stream().map(TBattleSpoils::getGoodsPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            user.setFinalGoodsPrice(finalGoodsPrice);
            /**对战箱子开箱信息*/
            tBattleBoxMapper.insertTBattleBoxBatch(user.getTBattleBoxList());
            /**更新对战用户状态*/
            tBattleUserMapper.updateBattleUserStatus(user.getBattleruserId(),user.getDzStatus(),user.getBattleFee(),finalGoodsPrice,
                    user.getUserSeed(),user.getServerSeed(),user.getCommonHash(),user.getRollValue(),user.getNonce());

            /**粉丝对战*/
            BigDecimal actualCost = user.getCost();
            if(battleInfo.getBattleType().equals(Constants.BATTLETYPE3) && user.getUserType().equals(Constants.USERTYPE0) && finalGoodsPrice.compareTo(battlefee)<0){
                BigDecimal bcfee = battlefee.subtract(finalGoodsPrice);
                actualCost = actualCost.subtract(bcfee);
            }
            BigDecimal consumeValue = actualCost.multiply(BigDecimal.valueOf(0.5)).setScale(2,BigDecimal.ROUND_HALF_UP);
             /**更新流水状态，纳入消费*/
            int count = balanceChangeMapper.updateBalanceChangeStatus(user.getUserId(),battleId,consumeValue,finalGoodsPrice,actualCost);
        });

        /**对战最终所得饰品*/
        tBattleSpoilsMapper.batchInsert(tBattleSpoilsList);
        /**用户背包*/
        tBackpackMapper.insertTBackpackBatch(tBackpackList);
        /**更新对战状态*/
        battleInfo.setBattleStatus(Constants.BATTLEINFOSTATUS1);
        battleInfo.setBattleTime(DateUtils.getNowDate());
        tBattleInfoMapper.updateTBattleInfo(battleInfo);

        /**如果是粉丝对战，有粉丝补偿策略*/
        if(battleInfo.getBattleType().equals(Constants.BATTLETYPE3)){
            battleUserList.forEach(user -> {
                BigDecimal bcfee = BigDecimal.ZERO;
                if(user.getUserType().equals(Constants.USERTYPE0)){/**粉丝对战仅限普通用户*/
                    if(user.getFinalGoodsPrice().compareTo(battlefee)<0){
                        bcfee = battlefee.subtract(user.getFinalGoodsPrice());

                        /**补偿粉丝金额*/
                        TUser tUser = tUserMapper.selectTUserById(user.getUserId());
                        BigDecimal afterBalance= tUser.getUserBalance();

                        tUser.setUpdateTime(DateUtils.getNowDate());
                        tUser.setUserBalance(afterBalance.add(bcfee));
                        int row1 = tUserMapper.updateTUserBalance(tUser);
                        if(row1 == 0){
                            throw new CustomException("余额变更异常");
                        }

                        TBalanceChange balanceChange1 = new TBalanceChange();
                        balanceChange1.setUserId(user.getUserId());
                        balanceChange1.setBalanceBefore(afterBalance);
                        balanceChange1.setBalanceAfter(afterBalance.add(bcfee));
                        balanceChange1.setOperationType(Constants.OPERATIONTYPE62);
                        balanceChange1.setFrequency(1);
                        balanceChange1.setFee(bcfee);
                        balanceChange1.setCorrespondingid(battleId);
                        balanceChange1.setCreateTime(DateUtils.getNowDate());
                        balanceChange1.setSecondCurrencyBefore(tUser.getSecondCurrency());
                        balanceChange1.setSecondCurrencyAfter(tUser.getSecondCurrency());
                        balanceChange1.setConsumeValue(BigDecimal.ZERO);
                        balanceChange1.setProfitPrice(BigDecimal.ZERO);
                        balanceChangeMapper.insertTBalanceChange(balanceChange1);
                    }
                }
                user.setBcFee(bcfee);
            });
        }
        /**普通用户和主播才计算消费流水*/
        battleUserList.stream().forEach(user -> {
            BigDecimal actualCost = user.getCost().subtract(user.getBcFee());
            BigDecimal consumeValue = actualCost.multiply(BigDecimal.valueOf(0.5)).setScale(2,BigDecimal.ROUND_HALF_UP);
            /**只有在消费计量值大于0的情况下主播和普通用户才计算战令和vip等级*/
            if((user.getUserType().equals(Constants.USERTYPE0) || user.getUserType().equals(Constants.USERTYPE1)) && consumeValue.compareTo(BigDecimal.ZERO)>0){
                tVipUserService.vipStreamHandleV2(user.getUserId(),consumeValue);
                tWarService.computeWarFlow(user.getUserId(),consumeValue);
            }
        });
        Map resmap = new LinkedHashMap();
        resmap.put("battleId",battleId);
        resmap.put("battleStatu",Constants.BATTLEINFOSTATUS1);
        return Response.success(resmap);
    }

    public TBackpack toTBackpack(TBattleBox tBattleBox,TBattleUser winUser,String bbId){
        TBackpack backpack = new TBackpack();
        backpack.setBbId(bbId);
        backpack.setUserId(winUser.getUserId());
        if(winUser.getUserId().equals(tBattleBox.getUserId())){
            backpack.setOpenBoxPrice(tBattleBox.getBoxPrice());
        }else {
            backpack.setOpenBoxPrice(new BigDecimal(0));
        }
        backpack.setGoodsId(tBattleBox.getGoodsId());
        backpack.setGoodsBelongingType(Constants.GOOGSBLTYPE5);
        backpack.setGoodsBelongingId(tBattleBox.getBattleId());
        backpack.setGoodsBelongingName(tBattleBox.getBoxName());
        backpack.setGoodsPrice(tBattleBox.getGoodsPrice());
        backpack.setGoodsExprice(tBattleBox.getGoodsExprice());
        backpack.setBbStatus(Constants.BBSTATUS0);
        backpack.setDelFlag(Constants.SUCCESS);
        backpack.setCreateTime(DateUtils.getNowDate());
        backpack.setGoodsNum(1);
        backpack.setGoodsType(tBattleBox.getGoodsType());
        backpack.setUserPromotersId(winUser.getUserPromotersId());
        backpack.setAuditStatus(Constants.AUDITSTATUS0);
        backpack.setBbGoodsName(tBattleBox.getTGoods().getGoodsName());
        backpack.setBbGoodsPic(tBattleBox.getTGoods().getGoodsPic());
        backpack.setBbGoodsGrate(tBattleBox.getTGoods().getGoodsGrate());
        backpack.setRemarkId(tBattleBox.getBoxId());
        backpack.setUserSeed(tBattleBox.getUserSeed());
        backpack.setCommonHash(tBattleBox.getCommonHash());
        backpack.setServerSeed(tBattleBox.getServerSeed());
        backpack.setRollValue(tBattleBox.getRollValue());
        backpack.setNonce(tBattleBox.getNonce());
        backpack.setRollValueRange(tBattleBox.getRollValueRange());
        return backpack;
    }

    public TBackpack toBcTBackpack(TGoods bcGoods,TBattleUser failUser,String bbId){
        /**失败者获得保底饰品*/
        TBackpack backpack = new TBackpack();
        backpack.setBbId(bbId);
        backpack.setUserId(failUser.getUserId());
        backpack.setGoodsId(bcGoods.getGoodsId());
        backpack.setGoodsBelongingType(Constants.GOOGSBLTYPE6);
        backpack.setGoodsBelongingId(failUser.getBattleId());
        backpack.setGoodsBelongingName("对战保底饰品");
        backpack.setGoodsPrice(bcGoods.getGoodsPrice());
        backpack.setGoodsExprice(bcGoods.getGoodsExprice());
        backpack.setBbStatus(Constants.BBSTATUS0);
        backpack.setDelFlag(Constants.SUCCESS);
        backpack.setCreateTime(DateUtils.getNowDate());
        backpack.setGoodsNum(1);
        backpack.setGoodsType(bcGoods.getGoodsType());
        backpack.setUserPromotersId(failUser.getUserPromotersId());
        backpack.setOpenBoxPrice(failUser.getCost());
        backpack.setAuditStatus(Constants.AUDITSTATUS0);
        backpack.setBbGoodsName(bcGoods.getGoodsName());
        backpack.setBbGoodsPic(bcGoods.getGoodsPic());
        backpack.setBbGoodsGrate(bcGoods.getGoodsGrate());
        backpack.setRemarkId(null);
        return backpack;
    }

    @Override
    public Response<BattleInfoResp> battleInfoV2(String battleId, String userId) {
        /**获取对战房间信息*/
        TBattleInfo battleInfo = tBattleInfoMapper.selectTBattleInfoById(battleId);

        if (StringUtils.isNull(battleInfo)) {
            return Response.fail(Constants.FAILCODE, "此对战房间不存在！");
        }
        if (!Constants.SUCCESS.equals(battleInfo.getDelFlag())) {
            return Response.fail(Constants.FAILCODE, "此房间已过时关闭！");
        }
        if(Constants.BATTLETYPE3.equals(battleInfo.getBattleType()) && StringUtils.isNotEmpty(battleInfo.getFanPwd())){
            battleInfo.setIsFanPwd(true);
        }
        BattleInfoResp resp = BeanUtil.copyProperties(battleInfo,BattleInfoResp.class);
        if(resp.getHomeownerUserid().equals(userId)){
            resp.setIsHomeUser(true);
        }
        /**获取房间的对战箱子*/
        List<TBattleCreateBox> tBattleCreateBoxList = tBattleCreateBoxMapper.battleBoxListByBattleId(battleId);

        /**获取所有箱子ID*/
        List<String> boxIds = tBattleCreateBoxList.stream().map(TBattleCreateBox::getBoxId).distinct().collect(Collectors.toList());
        List<TGoods> tGoodsList = tGoodsMapper.battleBoxGoods(boxIds);
        Map<String, List<TGoods>> tGoodsMap = tGoodsList.stream()
                .collect(Collectors.groupingBy(TGoods::getGoodsBelongingId));

        /**设置对战箱子及其饰品信息*/
        List<BattleBoxVo> battleBoxVoList = tBattleCreateBoxList.stream().map(t -> toBattleBoxVo(t,tGoodsMap.get(t.getBoxId()))).collect(Collectors.toList());
        battleBoxVoList.forEach(box -> {
            List<TGoods> goods = tGoodsMap.get(box.getBoxId());
            List<BattleGoodsDto> battleGoodsDtoList = BeanUtil.copyToList(goods,BattleGoodsDto.class);
            box.setBattleGoodsDtoList(battleGoodsDtoList);
        });
        resp.setBattleBoxList(battleBoxVoList);

        List<TBattleUser> battleUserList = tBattleUserMapper.getBattleUserListByBattleId(battleId);
        List<BattleUserInfoDTO> battleUserInfoDTOList = BeanUtil.copyToList(battleUserList,BattleUserInfoDTO.class);
        battleUserInfoDTOList.forEach(user -> {
            if(user.getUserId().equals(resp.getHomeownerUserid())){
                user.setIsHomeUser(true);
            }
            if(user.getUserId().equals(userId)){
                user.setIsSelfUser(true);
            }
        });
        /**判断是否开启对战*/
        if(resp.getBattleStatus().equals(Constants.BATTLEINFOSTATUS0)){
            resp.setBattleUserList(battleUserInfoDTOList);
            return Response.success(resp);
        }

        /**设置对战用户信息以及对战箱子开出饰品信息*/
        List<TBattleBox> tBattleBoxList = tBattleBoxMapper.boxListV2ByBattleId(battleId);
        Map<String, List<TBattleBox>> tBattleBoxMap = tBattleBoxList.stream()
                .collect(Collectors.groupingBy(TBattleBox::getUserId));

        /**用户最终得到的对战饰品信息*/
        List<TBattleSpoils> tBattleSpoilsList = tBattleSpoilsMapper.findByBattleId(battleId);
        Map<String, List<TBattleSpoils>> tBattleSpoilsMap = tBattleSpoilsList.stream()
                .collect(Collectors.groupingBy(TBattleSpoils::getUserId));

        battleUserInfoDTOList.forEach(user -> {
            List<TBattleSpoils> battleSpoilsList = tBattleSpoilsMap.get(user.getUserId());
            if(userId.equals(user.getUserId())){
                battleSpoilsList.forEach(spoil -> {
                    spoil.setObjectId(spoil.getBbId());
                });
            }
            user.setBattleSpoilsList(battleSpoilsList);

            List<TBattleBox> tBattleBoxList1 = tBattleBoxMap.get(user.getUserId());
            List<BattleBoxDTo> userOpenBoxList = BeanUtil.copyToList(tBattleBoxList1,BattleBoxDTo.class);
            user.setUserOpenBoxList(userOpenBoxList);
        });

        resp.setBattleUserList(battleUserInfoDTOList);
        return Response.success(resp);
    }
}
